//
// Created by 11510 on 2024/6/14.
//

#ifndef COWSTRING_COWSTRING_H
#define COWSTRING_COWSTRING_H
#include <iostream>
#include <string>
#include <cstring>
using std::cout;
using std::endl;
using std::string;
using std::ostream;
using std::cerr;

class CowString{
private:
    char* _pstr;
    /* int need 4B */
    static const int kRefCntLength = 4;
    class CharProxy{
    private:
        CowString& _self;
        int _idx;
    public:
        CharProxy(CowString &self, int idx)
                : _self(self), _idx(idx){
        }

        /**
         * 重载强转char，可以免去写重载输出流
         * @return
         */
        operator char(){
            printf("类型转换函数被调用\n");
            return _self._pstr[_idx];
        }

        char operator=(char ch);
//         删除重载输出流
//        friend ostream& operator<<(ostream& os, const CharProxy& rhs);
    };

public:
    CowString();
    CowString(const char* pstr);
    CowString(const CowString& rhs);
    CowString& operator=(const CowString& rhs);
    ~CowString();

    friend ostream& operator<<(ostream& os, const CowString& rhs);
//     删除重载输出流
//    friend ostream& operator<<(ostream& os, const CharProxy& rhs);

    int size() const{
        return strlen(_pstr);
    }
    const char* c_str() const{
        return _pstr;
    }

    int useCount(){
        return *(int*)(_pstr - kRefCntLength);
    }

    CowString::CharProxy operator[](int index);

private:
    void initRefCnt(){
        *(int*)(_pstr - kRefCntLength) = 1;
    }
    void increaseRefCnt(){
        (*(int*)(_pstr - kRefCntLength))++;
    }
    void decreaseRefCnt(){
        (*(int*)(_pstr - kRefCntLength))--;
    }
    char* malloc_fake(const char* pstr = nullptr){
        if(pstr){
            return new char[strlen(pstr) + 1 + kRefCntLength] + kRefCntLength;
        }
        return new char[1 + kRefCntLength] + kRefCntLength;
    }

    void release(){
        decreaseRefCnt();
        if(useCount() == 0){
            delete [] (_pstr - kRefCntLength);
            _pstr = nullptr;
            cout << "release" << endl;
        }
    }
};

ostream& operator<<(ostream& os, const CowString& rhs);
#endif //COWSTRING_COWSTRING_H
